/******************************************************************************
 * Copyright (C) 2017 Chengdu Dlhd information industry co. LTD.
 * All Rights Reserved.
 * 本软件为成都顶联互动信息产业有限公司开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、复制、修改或发布本软件.
 *****************************************************************************/
package net.dgg.dggcloud.service.iboss.utils;

import net.dgg.dggcloud.service.common.base.SessionManager;
import net.dgg.dggcloud.service.entity.user.User;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @class_name: dggcloud
 * @package: net.dgg.dggcloud.service.iboss.utils
 * @describe: TODO
 * @creat_user: 代杨
 * @creat_date: 2017/12/1
 * @creat_time: 9:29
 **/
public class DataWrap {
    public static final String GET = "get";
    public static final String SET = "set";

    public static final String CREATE_TIME = "CreateTime";
    public static final String CREATER_ID = "CreaterId";
    public static final String CREATER_NAME = "CreaterName";
    public static final String CREATER_ORG_ID = "CreaterOrgId";

    public static final String UPDATE_TIME = "UpdateTime";
    public static final String UPDATER_ID = "UpdaterId";
    public static final String UPDATER_NAME = "UpdaterName";
    public static final String UPDATER_ORG_ID = "UpdaterOrgId";


    /**
     * 对entity进行 保存 前的封装，但是 不调用 保存方法！
     *
     * @param entity 要封装的实体类
     * @param <T>
     * @return
     */
    public static <T> T saveWrap(T entity) {
        if (entity != null) {
            User user = SessionManager.getCurrentUser();
            Class clazz = entity.getClass();

            setVal(clazz, entity, CREATER_ID, user.getId(), Long.class);
            setVal(clazz, entity, CREATER_NAME, (user.getName() + "(" + user.getLoginName() + ")"), String.class);
            setVal(clazz, entity, UPDATER_ORG_ID, user.getOrgId(), Long.class);
            setVal(clazz, entity, CREATE_TIME, new Date(), Date.class);

//            setState(entity, "State");
//            setState(entity, "Flag");
        }
        return entity;
    }

    /**
     * 对entity进行 更新 前的封装，但是 不调用 更新方法！
     *
     * @param entity 要封装的实体类
     * @param <T>
     * @return
     */
    public static <T> T updateWraps(T entity) {
        if (entity != null) {
            User user = SessionManager.getCurrentUser();
            Class clazz = entity.getClass();

            setVal(clazz, entity, UPDATER_ID, user.getId(), Long.class);
            setVal(clazz, entity, UPDATER_NAME, (user.getName() + "(" + user.getLoginName() + ")"), String.class);
            setVal(clazz, entity, UPDATER_NAME, user.getOrgId(), Long.class);
            setVal(clazz, entity, UPDATE_TIME, new Date(), Date.class);
        }
        return entity;
    }

    /**
     * 私有方法，反射设置对象的值
     * 如果反射对象中没有对应的属性则跳过
     * 如果有对应的属性则进行赋值
     *
     * @param clazz
     * @param entity
     * @param mName
     * @param val
     * @param type
     */
    private static void setVal(Class clazz, Object entity, String mName, Object val, Class type) {
        try {
            Method method = clazz.getMethod(SET + mName, type);
            method.setAccessible(true);
            method.invoke(entity, val);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            return;
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 私有方法，反射获取对象的值
     * 如果反射对象中没有对应的属性则跳过
     * 如果有对应的属性则进行取值
     *
     * @param clazz
     * @param entity
     * @param mName
     * @return 值对象
     */
    private static Object getVal(Class clazz, Object entity, String mName) {
        Object result = null;
        try {
            Method method = clazz.getMethod(GET + mName);
            method.setAccessible(true);
            result = method.invoke(entity);
            return result;
        } catch (NoSuchMethodException e) {
            return null;
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 如果state为空设置为1;
     */
    private static void setState(Object obj, String name) {
        Class clz = obj.getClass();
        try {
            Method getMethod = clz.getMethod(GET + name);
            Method setMethod = clz.getMethod(SET + name, Integer.class);
            getMethod.setAccessible(true);
            Object val = getMethod.invoke(obj);
            if (val == null) {
                setMethod.invoke(obj, new Integer(1));
            }
        } catch (NoSuchMethodException e) {
        } catch (InvocationTargetException e) {
        } catch (IllegalAccessException e) {
        }
    }

    /**
     * 对象复制，如果有一样的属性且不为空则进行赋值。
     * 值得注意的是如果被复制对象中有空值的话不会覆盖新对象中的对应属性
     *
     * @param copy
     * @param copied
     * @param <T>
     * @return
     */
    public static <T> T copy(T copy, T copied) {
        Assert.notNull(copied, "被复制对象为空！");
        Assert.notNull(copy, "复制对象为空！");

        Class copyClz = copy.getClass();

        while (copyClz != Object.class) {
            copyVal(copy, copied, copyClz);
            copyClz = copyClz.getSuperclass();
        }

        return copy;
    }

    private static void copyVal(Object copy, Object copied, Class clz) {
        Method method;
        Object value;
        String propertyName;
        Field[] newFields = clz.getDeclaredFields();
        try {
            for (Field fid : newFields) {
                try {
                    propertyName = fid.getName().substring(0, 1).toUpperCase() + fid.getName().substring(1);
                    method = copied.getClass().getMethod("get" + propertyName);
                    value = method.invoke(copied);
                } catch (Exception e) {
                    continue;
                }
                if (value == null) {//为null的值 不用赋值
                    continue;
                }
                method = copy.getClass().getMethod("set" + propertyName, fid.getType());
                method.invoke(copy, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解决LONG失真 转成map
     *
     * @return
     */
    public static <T> Map<String, String> entityToMap(T obj) {
        Map<String, String> map = new HashMap<>();
        Class clz = obj.getClass();
        Field fields[] = clz.getDeclaredFields();
        for (Field f : fields) {
            try {
                f.setAccessible(true);
                String name = f.getName();
                Object value = f.get(obj);
                if (value != null) {
                    map.put(name, value.toString());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
}
